package lolcodecompiler;

import javax.swing.*;



public class MySyntaxAnalyzer implements SyntaxAnalyzer {

    @Override
    public void lolcode() 
    {

        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.DOC_BEGIN))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }

        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
        LOLCodeCompiler.lexer.getNextToken();
        
        
        switch(LOLCodeCompiler.token.toUpperCase())
        {
            case(LolTokens.COMMENT_BEGIN):
                comment();
            case(LolTokens.VAR_BEGIN):
                define();
            case(LolTokens.HEAD_BEGIN):
                head();
            
        }

        body();

        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.DOC_END))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }

        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);

        if(!LOLCodeCompiler.lexer.rest())
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
    }
        
    public void body()
    {
        
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.COMMENT_BEGIN))
        {
            comment();
            body();
        }
        innerText();
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.PARAGRAPH_BEGIN))
        {
            paragraph();
            body();
        }
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.BOLD_BEGIN))
        {
            bold();
            body();
        }
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.ITALICS_BEGIN))
        {
            italics();
            body();
        }
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.LIST_BEGIN))
        {
            list();
            body();
        }

    }

    @Override
    public void comment() 
    {
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);

        LOLCodeCompiler.lexer.getNextToken();	

        if(isText())
        {
            text();
        }

        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.COMMENT_END))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
        LOLCodeCompiler.lexer.getNextToken();
    }

    @Override
    public void head() 
    {
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);

        LOLCodeCompiler.lexer.getNextToken();	

        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.TITLE_BEGIN))
        {
            title();
        }

        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.HEAD_END))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        LOLCodeCompiler.parseTree.add(HtmlTokens.HEAD_END);
        LOLCodeCompiler.lexer.getNextToken();
    }

    @Override
    public void title() 
    {
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);

        LOLCodeCompiler.lexer.getNextToken();	

        if(isText())
        {
            text();
        }

        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.TITLE_END))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        LOLCodeCompiler.parseTree.add(HtmlTokens.TITLE_END);
        LOLCodeCompiler.lexer.getNextToken();
    }

    @Override
    public void paragraph() 
    {
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);

        LOLCodeCompiler.lexer.getNextToken();	

        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.VAR_BEGIN))
        {
            define();
        }
        innerPar();


        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.PARAGRAPH_END))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        LOLCodeCompiler.parseTree.add(HtmlTokens.PARAGRAPH_END);
        LOLCodeCompiler.lexer.getNextToken();

    }

    @Override
    public void bold() 
    {

        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token );
        LOLCodeCompiler.lexer.getNextToken();

        innerText();

        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.BOLD_END))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }

        LOLCodeCompiler.parseTree.add(HtmlTokens.BOLD_END);
        LOLCodeCompiler.lexer.getNextToken();

    }

    @Override
    public void italics() 
    {
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
        LOLCodeCompiler.lexer.getNextToken();

        innerText();

        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.ITALICS_END))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }

        LOLCodeCompiler.parseTree.add(HtmlTokens.ITALICS_END);
        LOLCodeCompiler.lexer.getNextToken();

    }

    @Override
    public void list() 
    {
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
        LOLCodeCompiler.lexer.getNextToken();

        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.ITEM_BEGIN))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        else
        {
            LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
            LOLCodeCompiler.lexer.getNextToken();
            
            innerList();
            if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.ITEM_END))
            {
                JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
                System.exit(0);
            }
            else
            {
                LOLCodeCompiler.parseTree.add(HtmlTokens.ITEM_END);
                LOLCodeCompiler.lexer.getNextToken();
                if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.ITEM_BEGIN))
                {
                    item();
                }
                if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.LIST_END))
                {
                    JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
                    System.exit(0);
                }
                LOLCodeCompiler.parseTree.add(HtmlTokens.LIST_END);
                LOLCodeCompiler.lexer.getNextToken();
            }
        }

    }
    
    @Override
    public void item() 
    {
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
        LOLCodeCompiler.lexer.getNextToken();

        innerList();

        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.ITEM_END))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }

        LOLCodeCompiler.parseTree.add(HtmlTokens.ITEM_END);
        LOLCodeCompiler.lexer.getNextToken();

        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.ITEM_BEGIN))
        {
            item();
        }

    }

    @Override
    public void audio() 
    {
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
        LOLCodeCompiler.lexer.getNextToken();

        if(isText())
        {
            text();
        }
        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.AUDIO_END))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }

        LOLCodeCompiler.parseTree.add(HtmlTokens.AUDIO_END);
        LOLCodeCompiler.lexer.getNextToken();
    }

    @Override
    public void video() 
    {
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
        LOLCodeCompiler.lexer.getNextToken();

        if(isText())
        {
            text();
        }
        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.VIDEO_END))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }

        LOLCodeCompiler.parseTree.add(HtmlTokens.VIDEO_END);
        LOLCodeCompiler.lexer.getNextToken();


    }

    @Override
    public void define() 
    {
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
        LOLCodeCompiler.lexer.getNextToken();

        if(LOLCodeCompiler.token.startsWith("#"))
        {
            JOptionPane.showMessageDialog(null, "#ERROR", "Invalid variable declartion" , JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        variable();

        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.ITS))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
        LOLCodeCompiler.lexer.getNextToken();

        if(LOLCodeCompiler.token.startsWith("#"))
        {
            System.err.println("Syntax Error: Invalid variable decllaration");
            System.exit(0);
        }
        defineVariable();
        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.VAR_END))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
        LOLCodeCompiler.lexer.getNextToken();
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.VAR_BEGIN))
        {
            define();
        }
    }

    @Override
    public void use() 
    {
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
        LOLCodeCompiler.lexer.getNextToken();

        if(LOLCodeCompiler.token.startsWith("#"))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }

        while(LOLCodeCompiler.token.endsWith(" "))
        {
            LOLCodeCompiler.token = LOLCodeCompiler.token.substring(0, LOLCodeCompiler.token.length() - 1);
        }

        String s = "";

        for(int i = LOLCodeCompiler.allTags.size() - 1; i >= 0; i--)
        {
            if(LOLCodeCompiler.allTags.get(i).lol.equals(LOLCodeCompiler.token))
            {
                s = LOLCodeCompiler.allTags.get(i).html;
                break;
            }
        }

        if(s.isEmpty()){
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }

        LOLCodeCompiler.parseTree.add(s);
        LOLCodeCompiler.lexer.getNextToken();

        if(!LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.USE_END))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token","#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
        LOLCodeCompiler.lexer.getNextToken();

    }

    public void innerText() {
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.USE_BEGIN))
        {
            use();
            innerText();
        }
        if(isText())
        {
            text();
            innerText();
        }
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.NEWLINE))
        {
            newline();
            innerText();
        }
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.AUDIO_BEGIN))
        {
            audio();
            innerText();
        }
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.VIDEO_BEGIN))
        {
            video();
            innerText();
        }
    }

    public void text() 
    {
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
        LOLCodeCompiler.lexer.getNextToken();
    }

    public void variable() 
    {
        while(LOLCodeCompiler.token.endsWith(" "))
        {
            LOLCodeCompiler.token = LOLCodeCompiler.token.substring(0, LOLCodeCompiler.token.length() - 1);
        }
        if(LOLCodeCompiler.token.contains(" "))
        {
            JOptionPane.showMessageDialog(null, "#ERROR invalid token: " + LOLCodeCompiler.token, "#SYNTAX ERROR", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        LOLCodeCompiler.allTags.add(new Tags(LOLCodeCompiler.token, ""));
        LOLCodeCompiler.lexer.getNextToken();
    }
    
    public void defineVariable() 
    {
        LOLCodeCompiler.allTags.get(LOLCodeCompiler.allTags.size()- 1).html = " " + LOLCodeCompiler.token + " ";
        LOLCodeCompiler.lexer.getNextToken();
    }
     public void newline()
    {
        LOLCodeCompiler.parseTree.add(LOLCodeCompiler.token);
        LOLCodeCompiler.lexer.getNextToken();

        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.NEWLINE))
        {
            newline();
        }

    }
    public void innerList()
    {
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.BOLD_BEGIN))
        {
            bold();
            innerList();
        }
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.ITALICS_BEGIN))
        {
            italics();
            innerList();
        }
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.LIST_BEGIN))
        {
            list();
            innerList();
        }
        innerText();
    }

    public void innerPar()
    {
        innerText();
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.BOLD_BEGIN))
        {
            bold();
            innerPar();
        }
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.ITALICS_BEGIN))
        {
            italics();
            innerPar();
        }
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.LIST_BEGIN))
        {
            list();
            innerPar();
        }
        if(LOLCodeCompiler.token.equalsIgnoreCase(LolTokens.NEWLINE))
        {
            newline();
            innerPar();
        }
    }
    
    public boolean isText()
    {
        return !LOLCodeCompiler.token.startsWith("#");
    }
}